#ifndef _IWINDOW_H_
#define _IWINDOW_H_

#ifdef _WIN32
    #include <Windows.h>
	#undef WINGDIAPI
	#undef min
	#undef max
	#undef far
	#undef near
#endif

#include <ctime>
#include <BFont>
#include <BImage>
#include <BCursor>
#include <BDialog>
#include <BOpenGL>
#include "ITextBlock.h"

#ifdef linux
    #include <unistd.h>
    #include <X11/Xlib.h>
	#include <GL/glx.h>
#endif

namespace BWE
{
	class IWindow : public BThing
	{
	public:
		IWindow(BWidget* widget);
		~IWindow();

		bool create();
		bool destroy();

		bool makeCurrent(bool yes);
		bool swapBuffers();

		bool setWindowTitle(const BString& title);
		BString getWindowTitle();

		void setWindowPos(const BPoint& pos);
		BPoint getWindowPos();

		void setWindowSize(const BSize& size);
		BSize getWindowSize();

		bool setWindowIcon(const BIcon* icon);
		void setFrameless(bool frameless);

		bool isMaximized();
		bool isMinimized();
		bool isFullScreen();

		void showNormal();
		void showMaximized();
		void showMinimized();
		void showFullScreen();
		void hideWindow();

	public:
		void update();
		void fresh();
		void frame();
		void focus(BWidget* widget);
		bool popup(BWidget* widget, bool flag);
		void freshCursor();
		
		void freshWidget(BWidget* widget, const BEvent& event);
		void frameWidget(BWidget* widget);
		void updateWidget(BWidget* widget, const BEvent& event);

		void drawWindow();
		void drawWidget(BWidget* widget, const BRect& clip, const BPoint& offset, int frameHeight);
		void drawPopupWidget(BWidget* widget, const BRect& clip, const BPoint& offset, int frameHeight);
		void drawCursor();
		void drawDrag();
		void drawTips();

		BWidget* widgetUnderPoint(const BPoint& point);
		BWidget* findWidget(BWidget* widget, const BPoint& point, const BRect& clip);
		BWidget* findPopupWidget(BWidget* widget, const BPoint& point, const BRect& clip);

		void procMousePress(BMouseEvent& mouseEvent);
		void procMouseRelease(BMouseEvent& mouseEvent);
		void procMouseMove(BMouseEvent& mouseEvent);
		void procMouseWheel(BMouseEvent& mouseEvent);
		void procDragMove(BDragEvent& dragEvent);
		void procDragDrop(BDragEvent& dragEvent);

	public:
		BWidget*			boss;
		bool				shown;
		clock_t				close_time;

		BEvent				event;
		BDrag*				drag;
		bool				refresh;
		bool				focusing;
		bool				tipsShown;
		BPoint				tipsPoint;
		clock_t				tipsTick;
		BRect				currentRect;

		BCursorHolder		hoverCursor;
		BWidget*			hoverWidget;
		BWidget*			focusWidget;
		BWidgetArray		popupWidgets;
		BBoolArray			keyStates;

		Button				mouse_button;
		bool				mouse_pressed;
		double				mouse_pressed_time;
		BPoint				mouse_pressed_pos;
		BReal				mouse_click_time;
		BPoint				mouse_click_pos;
		ITextBlock			tipsBlock;

#ifdef linux
		Display*		display;
		Screen*			screen;
		Window			rootHwnd;
		Window     		hwnd;
		int				style;
		GLXContext		context;
		Cursor			fontCursors[160];
		Atom 			wmDeleteWindow;
		bool procEvent(const XEvent& event);
		Key filterKey(KeySym keysym);
#endif

#ifdef _WIN32
		HWND				hwnd;
		bool				mouseInside;
		DWORD				style;
		HDC					hdc;
		HGLRC				context;
		bool procMessage(UINT message, WPARAM wParam, LPARAM lParam);
		Key filterKey(WPARAM wParam);
#endif
	};

	typedef BHolder<IWindow> IWindowHolder;

#ifdef _WIN32
	LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
	HGLRC CreateContext(HDC hdc);
#endif

#ifdef linux

#endif

}

#endif
